using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using SpaceMan.Physics;
using SpaceMan.Entities;
using SpaceMan.Particles;

namespace SpaceMan
{
    public enum ColliderType
    {
        Circle,
        Rectangle
    }

    public enum DrawMode
    {
        Texture,
        Glow,
        TextureAnim,
        DM_Count
    }

    public enum HitDirection
    {
        None,
        Vertical,
        Horizontal
    }

    public enum DamageAffinity
    {
        Allied,
        Enemy,
        Other

    }


    public struct physicsState
    {
        public Vector2 Pos;
        public Vector2 V;
    }

    public struct physicsStateDerivative
    {
        public Vector2 DX;
        public Vector2 DV;
    }

    public struct AnimationStructure
    {
        public string animationName;
        public float frameTime;
        public int startPosition;
        public bool animated;
        public bool loop;
        public int height, width, length;
        public Vector2 origin;
    }

    public struct DrawContents
    {
        public Texture2D Texture;
        public Texture2D GlowMask;
        public Dictionary<string, AnimationStructure> AnimationDictionary;
    }

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        Game game;
        MAN_ParticleManager ParticleManager;
        C_GameCamera gameCamera;
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        MAN_PhysicsManager physicsController;
        public MAN_EntityManager EntityManager;
        C_Drawing drawshit;
        int GlowSize = 4;
        float Swag;
        float intensity;
        float increment;
        FUNC_Shaders Shaders;
        Dictionary<DrawMode, RenderTarget2D> RTDictionary = new Dictionary<DrawMode, RenderTarget2D>();
        bool DrawHappened;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }


        protected override void Initialize()
        {
            graphics.PreferredBackBufferHeight = 720;
            graphics.PreferredBackBufferWidth = 1280;
            graphics.ApplyChanges();
            physicsController = new MAN_PhysicsManager();
            S_Global.OnGameStart(Content, graphics.GraphicsDevice, physicsController.addBody);
            List<PHY_Collider> templist = new List<PHY_Collider>();
           
            EntityManager = new MAN_EntityManager();
            ParticleManager = new MAN_ParticleManager();
            S_Global.secondINIT(EntityManager.giveEntity, EntityManager.AddEntity, ParticleManager.GiveParticle);
            drawshit = S_Global.getDraw("Tools/TestBackdrop");

            gameCamera = new C_GameCamera(Vector2.Zero, 1f, true);

            base.Initialize();
            game = new Game();
        }

        protected override void LoadContent()
        {

            spriteBatch = new SpriteBatch(GraphicsDevice);
            PresentationParameters pp = GraphicsDevice.PresentationParameters;
            RTDictionary.Add(DrawMode.Texture, new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, false, GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24));
            RTDictionary.Add(DrawMode.Glow, new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, false, GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24));
            RTDictionary.Add(DrawMode.TextureAnim, new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, false, GraphicsDevice.DisplayMode.Format, DepthFormat.Depth24));
            
            Shaders = new FUNC_Shaders(GraphicsDevice, Content.Load<Effect>("Shaders/GaussianBlur"), Content.Load<Effect>("Shaders/TextureAnimation"));
        }


        protected override void UnloadContent()
        {

        }


        protected override void Update(GameTime gameTime)
        {
            if (DrawHappened && game.IsActive)
            {
                S_Global.EachFrame(gameTime, 0.25f);
                GlowSize = (int)MathHelper.Clamp(GlowSize, 0, 9);

                gameCamera.Update(Vector2.Zero, 1f, 0f);
                physicsController.Update();
                gameCamera.UpdateConfinePosition();
                EntityManager.Update();
                ParticleManager.Update();
                drawshit.Update(new Vector2(0, 0), 0f, S_Global.CurrrentlyVisibleWorld().Width, S_Global.CurrrentlyVisibleWorld().Height, true, null);

                increment += 0.01f;
                Swag += 0.02f;
                intensity = ((float)Math.Sin(Swag) * 0.4f) + 0.6f;
                DrawHappened = false;
                base.Update(gameTime);
            }
        }

        protected override void Draw(GameTime gameTime)
        {

            //GraphicsDevice.SetRenderTarget(null);
            Dictionary<DrawMode, Texture2D> bufferDictionary = new Dictionary<DrawMode, Texture2D>();

            //for (DrawMode i = DrawMode.Texture; i != Enum.GetValues(typeof(DrawMode)).Cast<DrawMode>().Max(); i++)
            for (DrawMode i = DrawMode.Texture; i != DrawMode.DM_Count; i++)
            {

                GraphicsDevice.SetRenderTarget(RTDictionary[i]);
                GraphicsDevice.Clear(Color.Black);

                spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, null, null, null, null, gameCamera.TransformMatrix);
                {
                    
                    drawshit.Draw(spriteBatch, i, gameCamera.getDrawSpace(graphics.GraphicsDevice));
                    EntityManager.Draw(spriteBatch, i, gameCamera.getDrawSpace(graphics.GraphicsDevice));
                    ParticleManager.Draw(spriteBatch, i, gameCamera.getDrawSpace(graphics.GraphicsDevice));
                }

                spriteBatch.End();
                GraphicsDevice.SetRenderTarget(null);
                bufferDictionary.Add(i, (Texture2D)RTDictionary[i]);

                
            }

            bufferDictionary[DrawMode.Glow] = Shaders.GaussianBlur(spriteBatch, RTDictionary[DrawMode.Glow], bufferDictionary[DrawMode.Texture], 4, 1f);

            GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.DarkSlateBlue, 1.0f, 0);
            {
                List<Texture2D> renderList = new List<Texture2D>();
                renderList = bufferDictionary.Values.ToList();
                for (int i = 0; i < renderList.Count; i++)
                {
                    
                    if (bufferDictionary.ElementAt(i).Key == DrawMode.Texture)
                    {
                        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied);
                        spriteBatch.Draw(renderList[i], Vector2.Zero, Color.White);
                        spriteBatch.End();
                    }
                    else if (bufferDictionary.ElementAt(i).Key == DrawMode.Glow)
                    {
                        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Additive); // STC: Kolla denna: http://blogs.msdn.com/b/shawnhar/archive/2010/04/05/spritesortmode-immediate-in-xna-game-studio-4-0.aspx
                        spriteBatch.Draw(renderList[i], Vector2.Zero, Color.White);
                        spriteBatch.End();
                    }

                    
                }

            }

            DrawHappened = true;
            base.Draw(gameTime);
        }
    }
}
